<template>
  <div class="role-container">
    <el-card class="box-card">
      <!-- 搜索区域 -->
      <search-form v-model="queryParams" @search="handleQuery" @reset="handleReset">
        <el-form-item label="关键词">
          <el-input
            v-model="queryParams.keyword"
            placeholder="角色名称/编码"
            clearable
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
            <el-option label="启用" value="1" />
            <el-option label="禁用" value="0" />
          </el-select>
        </el-form-item>
      </search-form>

      <!-- 操作按钮区域 -->
      <table-toolbar
        :has-selected="selectedIds.length > 0"
        @add="handleAdd"
        @batch-delete="handleBatchDelete"
      >
        <!-- 添加自定义按钮 -->
        <template #buttons>
          <el-button type="success" :icon="RefreshRight" @click="handleRefresh">
            刷新
          </el-button>
        </template>
      </table-toolbar>

      <!-- 表格区域 -->
      <el-table
        v-loading="loading"
        :data="list"
        :height="tableHeight"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="角色名称" prop="name" min-width="120" show-overflow-tooltip />
        <el-table-column label="角色编码" prop="code" min-width="120" show-overflow-tooltip />
        <el-table-column label="排序" prop="sort" width="80" align="center" />
        <el-table-column label="状态" align="center" width="80">
          <template #default="{ row }">
            <el-switch
              v-model="row.status"
              :active-value="'1'"
              :inactive-value="'0'"
              @change="handleStatusChange(row)"
            />
          </template>
        </el-table-column>
        <el-table-column label="备注" prop="remark" min-width="150" show-overflow-tooltip />
        <el-table-column label="创建时间" prop="createTime" min-width="160" show-overflow-tooltip />
        <el-table-column label="操作" width="200" align="center" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link :icon="Edit" @click="handleUpdate(row)">
              编辑
            </el-button>
            <el-button type="primary" link :icon="Menu" @click="handlePermission(row)">
              权限
            </el-button>
            <el-button
              type="danger"
              link
              :icon="Delete"
              @click="handleDelete(row)"
              v-if="row.code !== 'ROLE_ADMIN'"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页区域 -->
      <pagination
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        :total="total"
        @pagination="getList"
      />

      <!-- 角色表单对话框 -->
      <el-dialog
        v-model="dialog.visible"
        :title="dialog.title"
        width="500px"
        append-to-body
        @close="resetForm"
      >
        <el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
          <el-form-item label="角色名称" prop="name">
            <el-input v-model="form.name" placeholder="请输入角色名称" />
          </el-form-item>
          <el-form-item label="角色编码" prop="code">
            <el-input 
              v-model="form.code" 
              placeholder="请输入角色编码"
              :disabled="form.id !== undefined"
            />
          </el-form-item>
          <el-form-item label="排序" prop="sort">
            <el-input-number v-model="form.sort" :min="0" :max="999" />
          </el-form-item>
          <el-form-item label="状态">
            <el-radio-group v-model="form.status">
              <el-radio value="1">启用</el-radio>
              <el-radio value="0">禁用</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="备注">
            <el-input
              v-model="form.remark"
              type="textarea"
              placeholder="请输入备注"
              maxlength="200"
              show-word-limit
            />
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="dialog.visible = false">取 消</el-button>
            <el-button type="primary" @click="submitForm" :loading="submitLoading">
              确 定
            </el-button>
          </div>
        </template>
      </el-dialog>

      <!-- 分配权限对话框 -->
      <el-dialog
        v-model="permissionDialog.visible"
        title="分配权限"
        width="600px"
        append-to-body
        destroy-on-close
      >
        <el-form label-width="80px">
          <el-form-item label="角色名称">
            <el-input v-model="permissionDialog.roleName" disabled />
          </el-form-item>
          <el-form-item label="权限">
            <el-tree
              ref="menuTreeRef"
              :data="menuTree"
              :props="{ label: 'title', children: 'children' }"
              show-checkbox
              node-key="id"
              :default-checked-keys="permissionDialog.menuIds"
              :default-expand-all="true"
              :check-strictly="false"
              @check="handleTreeCheck"
            />
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="permissionDialog.visible = false">取 消</el-button>
            <el-button type="primary" @click="submitPermission" :loading="submitLoading">
              确 定
            </el-button>
          </div>
        </template>
      </el-dialog>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from "vue";
import { Edit, Delete, Menu, RefreshRight } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox, type TreeInstance } from "element-plus";
import { useCrud } from "@/hooks/useCrud";
import {
  getRolePageList,
  addRole,
  updateRole,
  deleteRole,
  batchDeleteRole,
  getRoleMenus,
  assignRoleMenus,
  getRoleMenuPermissions,
} from "@/api/system/role";
import { getMenuTree } from "@/api/system/menu";
import SearchForm from "@/components/base/SearchForm.vue";
import TableToolbar from "@/components/base/TableToolbar.vue";
import Pagination from "@/components/base/Pagination.vue";
import { isSuccess } from '@/api/system/types'

// 表单校验规则
const rules = {
  name: [
    { required: true, message: "请输入角色名称", trigger: "blur" },
    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
  ],
  code: [
    { required: true, message: "请输入角色编码", trigger: "blur" },
    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
    { pattern: /^[A-Z_]+$/, message: "只能包含大写字母和下划线", trigger: "blur" },
  ],
  sort: [{ required: true, message: "请输入排序", trigger: "blur" }],
};

// 使用通用 CRUD hooks
const {
  queryParams,
  loading,
  list,
  total,
  selectedIds,
  dialog,
  formRef,
  form,
  getList,
  handleQuery,
  handleReset,
  handleSelectionChange,
  handleAdd,
  handleUpdate,
  submitForm,
  handleDelete,
  handleBatchDelete,
} = useCrud({
  listApi: getRolePageList,
  addApi: addRole,
  updateApi: updateRole,
  deleteApi: deleteRole,
  batchDeleteApi: batchDeleteRole,
  formRules: rules,
  defaultForm: {
    name: "",
    code: "",
    sort: 0,
    status: "1",
    remark: "",
  },
});

// 提交状态
const submitLoading = ref(false);

// 权限对话框
const menuTreeRef = ref<TreeInstance>();
const menuTree = ref([]);
const permissionDialog = reactive({
  visible: false,
  roleId: undefined as number | undefined,
  roleName: "",
  menuIds: [] as number[],
  halfCheckedIds: [] as number[]
});

// 处理树节点选中状态变化
const handleTreeCheck = (node: any, checkedInfo: any) => {
  permissionDialog.menuIds = checkedInfo.checkedKeys;
  permissionDialog.halfCheckedIds = checkedInfo.halfCheckedKeys;
};

// 处理权限数据
const processMenuPermissions = (menus: MenuPermissionVO[]) => {
  const checkedKeys: number[] = [];
  const halfCheckedKeys: number[] = [];
  
  const traverse = (nodes: MenuPermissionVO[]) => {
    nodes.forEach(node => {
      if (node.checked) {
        checkedKeys.push(node.id);
      } else if (node.halfChecked) {
        halfCheckedKeys.push(node.id);
      }
      if (node.children?.length) {
        traverse(node.children);
      }
    });
  };
  
  traverse(menus);
  return { checkedKeys, halfCheckedKeys };
};

// 分配权限
const handlePermission = async (row: any) => {
  permissionDialog.roleId = row.id;
  permissionDialog.roleName = row.name;
  permissionDialog.visible = true;
  permissionDialog.menuIds = []; // 清空之前的选中状态
  permissionDialog.halfCheckedIds = []; // 清空之前的半选状态

  try {
    const [menuRes, permissionRes] = await Promise.all([
      getMenuTree(),
      getRoleMenuPermissions(row.id),
    ]);
    
    if (isSuccess(menuRes) && isSuccess(permissionRes)) {
      menuTree.value = menuRes.data;
      const { checkedKeys, halfCheckedKeys } = processMenuPermissions(permissionRes.data);
      
      // 等待DOM更新后设置选中状态
      await nextTick();
      if (menuTreeRef.value) {
        menuTreeRef.value.setCheckedKeys(checkedKeys);
      }
      permissionDialog.menuIds = checkedKeys;
      permissionDialog.halfCheckedIds = halfCheckedKeys;
    } else {
      throw new Error("获取数据失败");
    }
  } catch (error: any) {
    ElMessage.error(error.message || "获取权限信息失败");
    permissionDialog.visible = false;
  }
};

// 提交权限
const submitPermission = async () => {
  if (!menuTreeRef.value || !permissionDialog.roleId) return;
  
  try {
    submitLoading.value = true;
    const checkedKeys = menuTreeRef.value.getCheckedKeys(false) as number[];
    const halfCheckedKeys = menuTreeRef.value.getHalfCheckedKeys() as number[];
    
    // 合并全选和半选的节点
    const allSelectedKeys = [...new Set([...checkedKeys, ...halfCheckedKeys])];
    
    await assignRoleMenus(permissionDialog.roleId, allSelectedKeys);
    ElMessage.success("分配权限成功");
    permissionDialog.visible = false;
  } catch (error: any) {
    ElMessage.error(error.message || "分配权限失败");
  } finally {
    submitLoading.value = false;
  }
};

// 处理状态变更
const handleStatusChange = async (row: any) => {
  try {
    await updateRole({
      id: row.id,
      status: row.status,
    });
    ElMessage.success("修改状态成功");
  } catch (error: any) {
    row.status = row.status === "1" ? "0" : "1";
    ElMessage.error(error.message || "修改状态失败");
  }
};

// 刷新列表
const handleRefresh = () => {
  getList();
};

// 重置表单
const resetForm = () => {
  if (formRef.value) {
    formRef.value.resetFields();
  }
  form.value = {
    name: "",
    code: "",
    sort: 0,
    status: "1",
    remark: "",
  };
};

// 表格高度自适应
const tableHeight = ref(500);

const calculateTableHeight = () => {
  const windowHeight = window.innerHeight;
  const otherHeight = 300;
  tableHeight.value = windowHeight - otherHeight;
};

onMounted(() => {
  getList();
  calculateTableHeight();
  window.addEventListener("resize", calculateTableHeight);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", calculateTableHeight);
});
</script>

<style lang="scss" scoped>
.role-container {
  height: 100%;

  .box-card {
    height: 100%;
    display: flex;
    flex-direction: column;

    :deep(.el-card__body) {
      flex: 1;
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }
  }

  .el-table {
    flex: 1;
  }

  .pagination-container {
    margin-top: 20px;
    display: flex;
    justify-content: flex-end;
  }
}

// 响应式布局
@media screen and (max-width: 768px) {
  .role-container {
    .el-table {
      :deep(.el-table__cell) {
        padding: 8px 0;
      }
    }

    .pagination-container {
      :deep(.el-pagination) {
        .el-pagination__sizes {
          display: none;
        }
      }
    }
  }
}
</style>
